<template>
  <div class="main" ref="main">
    <input class="file" name="file" type="file" accept="image/*" @change="updateFace" v-show="false" multiple ref="input" />

    <!-- 预览 -->
    <div class="previewImage" v-if="props.readonly&&props.readonly==1" :style="`grid-template-columns:repeat(${columnCount}, minmax(0px, 1fr))`">
      <div class="img" v-for="(item,index) in imgs" :key="index" @click="imgsClick(item)">
        <img :src="item" alt="">
      </div>
    </div>

    <div class="imgs" v-else>
      <div class="img" v-for="(item,index) in imgs" :key="index" @click="imgsClick(item)" :style="`width:${imgSize}px`">
        <img :src="item" alt="">
        <!-- 删除 -->
        <div class="delect" @click.stop="delect(index)">×</div>
      </div>
      <div class="img plus" @click="inputClick" v-if="imgs.length<limitNum" :style="`width:${imgSize}px`">
        <div class="camera">
          <img src="https://oss.seenlove.com/images/1d2b776c720f99688187e6f736abe614.png" alt="">
        </div>
      </div>
    </div>

    <el-dialog v-model="dialogVisible" title="预览" width="800px" append-to-body>
      <img :src="dialogImageUrl" />
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
const { proxy } = getCurrentInstance();
const instance = getCurrentInstance();
import useCounterStore from "@/store/counter";
import { computed, nextTick, onMounted } from "vue";
const counter = useCounterStore();

let props = defineProps(["limit", "size", "modelValue", "valType", "readonly"]);

const emit = defineEmits(["update:modelValue"]);

//data
let imgs = ref([]);
let dialogVisible = ref(false);
let dialogImageUrl = ref("");
let columnCount = ref(0);

//computed
let limitNum = computed(() => {
  return props.limit ? props.limit : 1;
});

let imgSize = computed(() => {
  if (props.size) return props.size;
  return proxy.$utils.isMobile() ? 80 : 148;
});

onMounted(() => {
  getColumnCount();
});

//methods
let init = () => {
  imgs.value = [];
};

let getColumnCount = () => {
  nextTick(() => {
    if (proxy.$refs.main) {
      let mainWidth = proxy.$refs.main.getBoundingClientRect().width;
      let num = Math.floor(mainWidth / imgSize.value);
      columnCount.value = num ? num : 1;
    }
  });
};

let inputClick = () => {
  instance.refs.input.click();
};

let imgsClick = (item) => {
  dialogImageUrl.value = item;
  dialogVisible.value = true;
};

let updateFace = async (e) => {
  try {
    if (e.target.files.length == 0) return;
    let file = e.target.files;
    let imgsArr = [...imgs.value];
    if (imgsArr.length + file.length > limitNum.value) {
      return proxy.$utils.showToast(`最多只能上传${limitNum.value}张图片`, 0);
    }
    for (let index = 0; index < file.length; index++) {
      const element = file[index];
      let resp = await getFile(element);
      imgsArr.push(resp);
    }
    imgs.value = [...imgsArr];
  } catch (error) {
  } finally {
    e.target.value = "";
  }
};

let getFile = async (file) => {
  try {
    //验证图片格式大小信息
    const isJPG = file.type == "image/jpeg" || file.type == "image/png";
    const isLt2M = file.size / 1024 / 1024 < 10;
    if (!isJPG)
      return proxy.$utils.showToast("上传图片只能是 JPG 或 PNG 格式!", 0);
    if (!isLt2M) return proxy.$utils.showToast("上传图片大小不能超过 10MB!", 0);

    let resp = await counter.uploadFile(file);
    return resp;
  } catch (error) {
    proxy.$utils.showToast(error, 0);
  } finally {
  }
};
let delect = (index: Number) => {
  imgs.value.splice(index, 1);
};

//watch
// 当值发生变化，更新值
watch(
  () => props.modelValue,
  (newValue, oldValue) => {
    if (newValue) {
      let arr = props.valType == "arr" ? newValue : newValue.split(",");
      imgs.value = [...arr];
    } else {
      imgs.value = [];
    }
  },
  { immediate: true, deep: true }
);

watch(
  () => imgs.value,
  (newValue, oldValue) => {
    let isChange = true;
    if (newValue && !oldValue) isChange = false;
    if (
      newValue &&
      oldValue &&
      !proxy.$utils.isObjectValueEqual(newValue, oldValue)
    )
      isChange = false;
    if (isChange) {
      let con = props.valType == "arr" ? newValue : newValue.toString();
      emit("update:modelValue", con);
    }
  },
  { deep: true, immediate: true }
);

defineExpose({ inputClick, init });
</script>

<style lang="scss" scoped>
.main {
  width: 100%;
}
img {
  width: 100%;
  display: block;
  object-fit: cover;
  height: 100%;
  border-radius: 5px;
}
.previewImage {
  display: grid;
  gap: 15px 15px;
}
.imgs {
  display: flex;
  flex-wrap: wrap;
  .camera {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 20px;
  }
  .img:hover .delect {
    display: block;
  }
  .plus {
    border-radius: 5px;
  }
  .img {
    background-color: #fbfdff;
    border: 0.5px dashed #c0ccda;
    box-sizing: border-box;
    cursor: pointer;
    position: relative;
    aspect-ratio: 1/1;
    margin: 0 15px 15px 0;
    .icon {
      font-size: 28px;
      color: #8c939d;
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
    }
    .delect {
      position: absolute;
      right: 0;
      top: 0;
      width: 20px;
      height: 20px;
      text-align: center;
      line-height: 20px;
      font-size: 15px;
      background-color: rgba(255, 255, 255, 0.7);
      user-select: none;
      cursor: pointer;
      display: none;
    }
    .delect:hover {
      background-color: rgba(31, 31, 31, 0.5);
      color: white;
    }
  }
}
</style>
